package p2p

import (
	"fmt"
	"net"
	"strings"
	"time"
)

//对等节点结构体
type Peer struct {
	Node
	conn    net.Conn
	rwready bool
	closed  chan struct{}
}

type ConnectedPeer struct {
	Peer Peer
	Next *ConnectedPeer
}

type ConnectedPeerHead struct {
	ConnectHead   *ConnectedPeer
	Number        int
	ConnectFinish *ConnectedPeer
}

var (
	//peerlist 	  ConnectedPeerHead
	userlist     ConnectedPeerHead
	peerlist     = make(map[string]Peer)
	peerwaitlist = make(map[string]Node)
	LocalIP      string
)

func GetPeerwait() {
	peerwaitlist = GetNodefromfile()
}

func InitPeer() {
	GetPeerwait()
	LocalIP = GetLocalIP()
}

//监听对等节点的连入 Port:8086
func ListenPeer() {
	listener, err := net.Listen("tcp", LocalIP+":8086") //创建监听
	if err != nil {
		fmt.Println(err)
		return
	}
	defer listener.Close()
NEXT:
	for {
		fmt.Println("等待连接节点...")
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println(err)
		}
		fmt.Println("Local IP ", conn.LocalAddr().String(), "Remote IP", conn.RemoteAddr().String())
		//如果对方主动连接了 就不再连接了
		addr := conn.RemoteAddr().String()
		addr = addr[:strings.IndexByte(addr, ':')]
		delete(peerwaitlist, addr)

		//判断连接是否重复
		for _, v := range peerlist {
			addr1 := v.conn.RemoteAddr().String()
			addr1 = addr1[:strings.IndexByte(addr1, ':')]
			if addr == addr1 {
				conn.Close()
				fmt.Println("对方重复连接已经挂断")
				break NEXT
			}
		}
		peerlist[addr] = Peer{
			peerwaitlist[addr],
			conn,
			false,
			make(chan struct{}, 1),
		}
	}
}

//监听用户的连入 Port:8087
func ListenUser() {
	listener, err := net.Listen("tcp", LocalIP+":8087") //创建监听
	if err != nil {
		fmt.Println(err)
		return
	}
	defer listener.Close()
	for {
		fmt.Println("等待连接节点...")
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println(err)
		}
		insertpeer(userlist, Peer{conn: conn})
		fmt.Println(conn)
	}
}

func ConnectPeer() {
	for {
		time.Sleep(1 * time.Second)
		for key, value := range peerwaitlist {
			go func() {
				var peer Peer
				peer.ID = value.ID
				peer.Name = value.Name
				peer.Address = value.Address
				peer.Port = value.Port
				str := peer.Address + ":" + peer.Port
				var err error
				peer.conn, err = net.Dial("tcp", str)
				if err != nil {
					fmt.Println("连接失败，错误：", err, "5秒后重试")
					return
				} else {
					fmt.Println("Connect Local IP ", peer.conn.LocalAddr().String(), "Remote IP", peer.conn.RemoteAddr().String())
					for _, v := range peerlist {
						addr1 := v.conn.RemoteAddr().String()
						addr1 = addr1[:strings.IndexByte(addr1, ':')]
						addr2 := v.conn.RemoteAddr().String()
						addr2 = addr2[:strings.IndexByte(addr2, ':')]
						if addr1 == addr2 {
							peer.conn.Close()
							fmt.Println("Sorry 重复连接已经挂断")
							return
						}
					}
					peer.rwready = false
					peer.closed = make(chan struct{})
					peerlist[peer.Address] = peer
					delete(peerwaitlist, key)
				}
			}()

		}
	}
}

func insertpeer(head ConnectedPeerHead, peer Peer) {
	var node ConnectedPeer
	node.Peer = peer
	node.Next = nil
	if head.Number == 0 {
		head.ConnectHead = &node
		head.Number++
		head.ConnectFinish = &node
	} else {
		head.Number++
		head.ConnectFinish.Next = &node
		head.ConnectFinish = &node
	}
}

func deletenode(head ConnectedPeerHead, peer Peer) {
	if head.Number == 0 {
		return
	} else {
		var temp *ConnectedPeer
		temp = head.ConnectHead
		if temp.Peer == peer {
			head.ConnectHead = temp.Next
			temp.Peer.conn.Close()
			head.Number--
			if head.Number == 0 {
				head.ConnectFinish = nil
			}
			peerwaitlist[peer.Address] = Node{ID: peer.ID, Name: peer.Name, Address: peer.Address, Port: peer.Port}
			return
		}
		for ; temp.Next != nil; temp = temp.Next {
			if temp.Next.Peer == peer {
				break
			}
		}
		if temp.Next == nil {
			return
		} else {
			head.Number--
			temp.Next.Peer.conn.Close()
			//节点的内存空间不知道释放没释放
			temp.Next = temp.Next.Next
			peerwaitlist[peer.Address] = Node{ID: peer.ID, Name: peer.Name, Address: peer.Address, Port: peer.Port}
		}
	}
}

func GetPeerNumber() int {
	return len(peerlist) + 1
}

func GetLocalIP() string {
	netInterfaces, err := net.Interfaces()
	if err != nil {
		fmt.Println("net.Interfaces failed, err:", err.Error())
		return ""
	}
	//如果安装有虚拟机 去除虚拟网卡
	for i := 0; i < len(netInterfaces); i++ {
		if (netInterfaces[i].Flags&net.FlagUp) != 0 && !isVirtual(netInterfaces[i]) {
			addrs, _ := netInterfaces[i].Addrs()
			for _, address := range addrs {
				if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
					if ipnet.IP.To4() != nil {
						return ipnet.IP.String()
					}
				}
			}
		}
	}
	//如果是虚拟机 保留虚拟网卡
	for i := 0; i < len(netInterfaces); i++ {
		if (netInterfaces[i].Flags & net.FlagUp) != 0 {
			addrs, _ := netInterfaces[i].Addrs()
			for _, address := range addrs {
				if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
					if ipnet.IP.To4() != nil {
						return ipnet.IP.String()
					}
				}
			}
		}
	}
	return ""
}

func isVirtual(p net.Interface) bool {
	//"00:05:69"; //vmware1
	//"00:0C:29"; //vmware2
	//"00:50:56"; //vmware3
	//"00:1c:14"; //vmware4
	//"00:1C:42"; //parallels1
	//"00:03:FF"; //microsoft virtual pc
	//"00:0F:4B"; //virtual iron 4
	//"00:16:3E"; //red hat xen , oracle vm , xen source, novell xen
	//"08:00:27"; //virtualbox

	virtualPrefix := make([]string, 0)
	virtualPrefix = append(virtualPrefix, "00:05:69")
	virtualPrefix = append(virtualPrefix, "00:0C:29")
	virtualPrefix = append(virtualPrefix, "00:50:56")
	virtualPrefix = append(virtualPrefix, "00:1C:14")
	virtualPrefix = append(virtualPrefix, "00:1C:42")
	virtualPrefix = append(virtualPrefix, "00:03:FF")
	virtualPrefix = append(virtualPrefix, "00:0F:4B")
	virtualPrefix = append(virtualPrefix, "00:16:3E")
	virtualPrefix = append(virtualPrefix, "08:00:27")

	for k := range virtualPrefix {
		if strings.HasPrefix(p.HardwareAddr.String(), virtualPrefix[k]) {
			return true
		}
	}
	return false
}
